#include "VisiyunSDK.h"
#include <QDebug>
#include <QSize>
#include <cstring>
#include <cstdint>
#include "VisiyunDevice.h"
#include <QPluginLoader>
#include <QImage>

Q_DECLARE_METATYPE(std::function<void(const QString&, const QImage&, int)>)
/**
 * @brief 构造函数
 * @param parent 父对象指针
 */
VisiyunSDK::VisiyunSDK(QObject *parent) : CameraSDKInterface(parent) {}
/**
 * @brief 析构函数（自动反初始化SDK）
 */
VisiyunSDK::~VisiyunSDK()
{
    closeAllDevices();
}

/**
 * @brief 关闭所有设备连接
 * @details 遍历所有已连接设备并关闭连接，清空映射表
 */
void VisiyunSDK::closeAllDevices()
{
    // 遍历所有设备并关闭连接
    for (auto it = m_deviceMap.begin(); it != m_deviceMap.end(); ++it) {
        VisiyunDeviceInfo& deviceInfo = it.value();
        
        // 释放参数设置Widget
        if (deviceInfo.pCameraParametersWidget) {
            delete deviceInfo.pCameraParametersWidget;
            deviceInfo.pCameraParametersWidget = nullptr;
        }
        
        // 释放触发设置对话框
        if (deviceInfo.pCameraTriggerSettings) {
            delete deviceInfo.pCameraTriggerSettings;
            deviceInfo.pCameraTriggerSettings = nullptr;
        }
        
        // 关闭并释放设备
        if (deviceInfo.pVisiyunDevice) {
            deviceInfo.pVisiyunDevice->close();
            delete deviceInfo.pVisiyunDevice;
            deviceInfo.pVisiyunDevice = nullptr;
        }
    }
    m_deviceMap.clear();
    qDebug() << "Closed all Visiyun camera connections";
}

/**
 * @brief 打开设备连接
 * @details 通过IP地址连接到Visiyun相机，成功后将IP与控制ID存入m_deviceMap
 * @param params QString类型的设备IP地址
 * @return 连接成功返回true，IP无效或连接失败返回false
 */
bool VisiyunSDK::openDevice(const QVariant& params)
{
    // 直接将参数转换为char数组
    QString ip = params.toString();
    const char* ipChar = ip.toUtf8().constData();
    if (!ipChar || strlen(ipChar) == 0) {
        qWarning() << "Invalid IP address parameter";
        return false;
    }
    // 直接传递char数组给连接函数
    VisiyunDevice* device = new VisiyunDevice(ip, this);
    if (!device->open()) {
        delete device;
        qWarning() << "Failed to connect to Visiyun camera at" << ip;
        return false;
    }
    
    // 创建并初始化设备信息结构体
    VisiyunDeviceInfo deviceInfo;
    deviceInfo.pVisiyunDevice = device;
    deviceInfo.pCameraTriggerSettings = nullptr;
    deviceInfo.pCameraParametersWidget = nullptr;
    
    m_deviceMap.insert(ip, deviceInfo); // 连接成功后存储设备实例信息

    return true;
}

/**
 * @brief 关闭指定设备连接
 * @details 根据IP地址关闭对应的设备连接并从映射表中移除
 * @param params QString类型的设备IP地址
 */
void VisiyunSDK::closeDevice(const QVariant& params)
{
    QString ip = params.toString();
    if (ip.isEmpty()) {
        qWarning() << "IP address parameter is required for uninitialize";
        return;
    }
    if (m_deviceMap.contains(ip)) {
        VisiyunDeviceInfo& deviceInfo = m_deviceMap[ip];
        
        // 释放参数设置Widget
        if (deviceInfo.pCameraParametersWidget) {
            delete deviceInfo.pCameraParametersWidget;
            deviceInfo.pCameraParametersWidget = nullptr;
        }
        
        // 释放触发设置对话框
        if (deviceInfo.pCameraTriggerSettings) {
            delete deviceInfo.pCameraTriggerSettings;
            deviceInfo.pCameraTriggerSettings = nullptr;
        }
        
        // 关闭并释放设备
        if (deviceInfo.pVisiyunDevice) {
            deviceInfo.pVisiyunDevice->close();
            delete deviceInfo.pVisiyunDevice;
            deviceInfo.pVisiyunDevice = nullptr;
        }
        
        m_deviceMap.remove(ip);
        qDebug() << "Closed connection to Visiyun camera at" << ip;
    } else {
        qWarning() << "No active connection found for IP:" << ip;
    }
}

/**
 * @brief 获取SDK名称
 * @return 固定返回"VisiyunSDK"
 */
QString VisiyunSDK::sdkName() const {
    return "VisiyunSDK";
}

/**
 * @brief 获取相机固件版本号
 * @return 字符串形式的固件版本号（如"V1.2.3"）
 */
QString VisiyunSDK::SDKVersion() const
{
    return "1.0.0";
}

/**
 * @brief 获取设备固件版本号
 * @param ip 设备IP地址
 * @return 成功返回固件版本号(整数形式)，设备不存在返回-1
 */
int VisiyunSDK::getDeviceFirmwareVersion(const QVariant& deviceId)
{
    QString ip = deviceId.toString();
    if (m_deviceMap.contains(ip)) {
        return m_deviceMap[ip].pVisiyunDevice->getFirmwareVersion();
    }
    qWarning() << "Device not found for IP:" << ip;
    return -1;
}

/**
 * @brief 获取设备像素尺寸
 * @param ip 设备IP地址
 * @return 成功返回像素尺寸(QSize)，设备不存在返回空尺寸
 */
QSize VisiyunSDK::getDevicePixelSize(const QVariant& deviceId)
{
    QString ip = deviceId.toString();
    if (m_deviceMap.contains(ip)) {
        return m_deviceMap[ip].pVisiyunDevice->getPixelSize();
    }
    qWarning() << "Device not found for IP:" << ip;
    return QSize();
}

/**
 * @brief 设置图像采集回调函数
 * @param ip 设备IP地址
 * @param callback 图像回调函数指针
 */
void VisiyunSDK::setImageCaptureCallback(const QVariant& deviceId, ImageCallback callback)
{
    QString ip = deviceId.toString();
    if (m_deviceMap.contains(ip)) {
        m_deviceMap[ip].pVisiyunDevice->setImageCallback(callback);
        m_deviceMap[ip].pVisiyunDevice->startCapture();
    } else {
        qWarning() << "Device not found for IP:" << ip;
    }
}

/**
 * @brief 取消图像采集回调函数
 * @param ip 设备IP地址
 */
void VisiyunSDK::unsetImageCaptureCallback(const QVariant& deviceId)
{
    QString ip = deviceId.toString();
    if (m_deviceMap.contains(ip)) {
        VisiyunDevice* device = m_deviceMap[ip].pVisiyunDevice;
        device->stopCapture();
        device->setImageCallback(nullptr);
    } else {
        qWarning() << "Device not found for IP:" << ip;
    }
}

/**
 * @brief 搜索局域网内可用的Visiyun相机设备
 * @param devices 输出参数，存储搜索到的设备IP地址列表
 * @return 搜索到设备返回true，未搜索到返回false
 */
bool VisiyunSDK::searchDevices(QList<QVariant>& devices)
{
    int cnt = 0;
    char ipArray[25][15];
    memset(ipArray, 0, sizeof(ipArray));
    cnt = VsyCam_SearchCamera(ipArray);
    if (cnt > 25) cnt = 25;
    devices.clear();
    for (int i = 0; i < cnt; i++)
    {
        QString ip(ipArray[i]);
        if (!ip.isEmpty()) {
            devices.push_back(QVariant(ip));
        }
    }
    if(devices.size() <= 0){
        devices.push_back(DEFAULT_CAMERA_IP);
    }
    return devices.size() > 0;
}

/**
 * @brief 获取快速参数设置Widget
 * @param deviceId 设备ID
 * @param parent 父Widget
 * @return 快速参数设置Widget指针
 */
QWidget* VisiyunSDK::getQuickParametersWidget(const QVariant& deviceId, QWidget* parent)
{
    QString ip = deviceId.toString();
    if (m_deviceMap.contains(ip)) {
        VisiyunDevice* device = m_deviceMap[ip].pVisiyunDevice;
        
        // 如果参数Widget不存在，则创建一个新的
        if (!m_deviceMap[ip].pCameraParametersWidget) {
            m_deviceMap[ip].pCameraParametersWidget = new CameraParametersWidget(device, parent);
            qDebug() << "Creating quick parameters widget for Visiyun camera at" << ip;
        }
        
        return m_deviceMap[ip].pCameraParametersWidget;
    }
    qWarning() << "Device not found for IP:" << ip;
    return nullptr;
}

/**
 * @brief 设置设备触发模式
 * @param deviceId 设备ID（IP地址）
 * @param triggerMode 触发模式，使用TRIGGER_MODE_*宏定义
 * @return 设置成功返回true，失败返回false
 */
bool VisiyunSDK::setDeviceTriggerMode(const QVariant& deviceId, int triggerMode)
{
    QString ip = deviceId.toString();
    if (m_deviceMap.contains(ip)) {
        VisiyunDevice* device = m_deviceMap[ip].pVisiyunDevice;
        
        // 将通用触发模式映射到VisiyunDevice支持的触发模式
        // VisiyunDevice支持：0=内触发, 1=外触发
        
        qDebug() << "Setting trigger mode for Visiyun camera at" << ip << ":" << triggerMode << "->";
        int result = device->setTriggerMode(triggerMode);
        
        if (result == 0) {
            qDebug() << "Successfully set trigger mode for Visiyun camera";
            return true;
        } else {
            qWarning() << "Failed to set trigger mode for Visiyun camera, error code:" << result;
            return false;
        }
    }
    
    qWarning() << "Device not found for IP:" << ip;
    return false;
}

bool VisiyunSDK::setDeviceParameters(const QVariant& deviceId, const QVariantMap& params)
{
    // 将deviceId转换为QString
    QString ip = deviceId.toString();
    
    // 检查设备是否存在
    if (!m_deviceMap.contains(ip)) {
        writeLog(QString("设备 %1 不存在").arg(ip), 2, true);
        return false;
    }
    
    // 获取设备实例
    VisiyunDevice* device = m_deviceMap[ip].pVisiyunDevice;
    
    // 调用设备的setParameters方法设置所有参数
    bool result = device->setParameters(params);
    
    if (result) {
        writeLog(QString("设备 %1 参数设置成功").arg(ip), 0, true);
    } else {
        writeLog(QString("设备 %1 参数设置失败").arg(ip), 2, true);
    }
    
    return result;
}

bool VisiyunSDK::getDeviceParameters(const QVariant& deviceId, QString& configName, QVariantMap& params)
{
    // 将deviceId转换为QString
    QString ip = deviceId.toString();
    
    // 检查设备是否存在
    if (!m_deviceMap.contains(ip)) {
        writeLog(QString("设备 %1 不存在").arg(ip), 2, true);
        return false;
    }
    
    // 设置配置名称
    configName = "VisiyunConfig";
    
    // 获取设备实例
    VisiyunDevice* device = m_deviceMap[ip].pVisiyunDevice;
    
    // 调用设备的getParameters方法获取所有参数
    params = device->getParameters();
    
    return true;
}

/**
 * @brief 获取设备参数
 * @param deviceId 设备ID
 * @return 设备参数映射，使用QVariantMap作为万能变量类型
 */
bool VisiyunSDK::setPresetParameters(const QVariantMap& params)
{
    Q_UNUSED(params)
    return true;
}

/**
 * @brief 设置预设参数
 * @param params 预设参数映射，使用QVariantMap作为万能变量类型
 * @return 设置成功返回true，失败返回false
 */
bool VisiyunSDK::getPresetParameters(QString& configName, QVariantMap& params)
{
    // 设置配置名称
    configName = "DefaultPreset";
    
    // 清空参数
    params.clear();
    
    return true;
}

/**
 * @brief 获取参数设置对话框
 * @param deviceId 设备ID
 * @param parent 父Widget
 * @return 参数设置对话框指针
 */
QDialog* VisiyunSDK::getParametersDialog(const QVariant& deviceId, QWidget* parent)
{
    QString ip = deviceId.toString();
    if (m_deviceMap.contains(ip)) {
        VisiyunDevice* device = m_deviceMap[ip].pVisiyunDevice;
        
        // 如果参数对话框不存在，则创建一个新的
        if (!m_deviceMap[ip].pCameraTriggerSettings) {
            m_deviceMap[ip].pCameraTriggerSettings = new CameraTriggerSettings(device, ip, parent);
        }
        
        return m_deviceMap[ip].pCameraTriggerSettings;
    }
    return nullptr;
}
